#ifndef CONFIG_H_
#define CONFIG_H_

#include "TimeStructure.h"
#include "BasicConfig.h"
#include "FileFunction.h"
#include "GhostFunction.h"
#include "listdialog.h"
#include "DataExportDialog.h"
#include "textprinter.h"
#include "Structures.h"
#include "DB_Manager.h"
#include "imagestructure.h"



#define RICHIESTA_PAESI "SELECT n.*, round((n.rgt-n.lft-1)/2,0) AS childs, count(*)+(n.lft>1) AS level, ((min(p.rgt)-n.rgt-(n.lft>1))/2) > 0 AS lower, (( (n.lft-max(p.lft)>1) )) AS upper FROM LUOGHI n, LUOGHI p WHERE n.lft BETWEEN p.lft AND p.rgt AND (p.root_id = n.root_id) AND (p.id != n.id OR n.lft = 1) GROUP BY n.root_id,n.id ORDER BY n.root_id,n.lft"
#define TABELLA_PAESI "LUOGHI"
typedef QMap<int,int> CheckRow;

/* numeri blob id per la tabella APPLICATION_SETTING */


#define _CURRENT_VERSION_ "1.4.4"


#define _PROGRAM_TITLE_ \
             QString("House Manager ETV version %1").arg(_CURRENT_VERSION_)


static inline QStringList config_language_short()
{
     QStringList Small_Language;
     Small_Language << "it" << "de" << "fr" << "en";
     return  Small_Language;
}

static inline QStringList config_language_long()
{
     QStringList Long_Language;
     Long_Language << "Italiano" << "Deutsch" << "Francais" << "English";
     return  Long_Language;
}





static inline QString UserLanguage()
{
     QString languser,languagesistem,langqt; 
	QLocale loci = QLocale::system();
             languser = getenv("LANG");
             languser = languser.toLower();
             languagesistem = loci.name();
             languagesistem = languagesistem.toLower();
	     languagesistem = languagesistem.left(2);
     /* Window XP Prof MUI Multiuser == stay only "c" language && user setting setenv !!! */
     if (languagesistem == "c") { 
         if (languser.size() > 2 && languser.contains("_")) {
             languagesistem = languser.left(2);
         }
     }
     return languagesistem;
}


#define FOPIMAGEDIR "Pictures/"



#define POINT_TO_CM(cm) ((cm)/28.3465058)
#define POINT_TO_MM(mm) ((mm)/2.83465058)
#define POINT_TO_DM(dm) ((dm)/283.465058)
#define POINT_TO_INCH(inch) ((inch)/72.0)
#define POINT_TO_PI(pi) ((pi)/12)
#define POINT_TO_DD(dd) ((dd)/154.08124)
#define POINT_TO_CC(cc) ((cc)/12.840103)



#define MM_TO_POINT(mm) ((mm)*2.83465058)
#define CM_TO_POINT(cm) ((cm)*28.3465058)
#define DM_TO_POINT(dm) ((dm)*283.465058)
#define INCH_TO_POINT(inch) ((inch)*72.0)
#define PI_TO_POINT(pi) ((pi)*12)
#define DD_TO_POINT(dd) ((dd)*154.08124)
#define CC_TO_POINT(cc) ((cc)*12.840103)




static inline QString StringXML( QString t )
{
  //the following checks are necessary before exporting
  //strings to XML. see http://hdf.ncsa.uiuc.edu/HDF5/XML/xml_escape_chars.html for details
  QString text = t;
  text.replace("&", "&amp;");   /*  qt4 toUtf8 dont replace && */
  text.replace("\"","&quot;");
  text.replace("'", "&apos;");
  text.replace("<", "&lt;");
  text.replace(">", "&gt;");
  text.replace("\n", "&#10;");
  text.replace("\r", "&#13;");
  return text;
}






/* grep nummer on [77] */
static inline int  BraketNummer( QString braket )
{
    int esanummer = 0;
    if (braket.startsWith("[")) {
       braket.replace(QString("["), QString("")); 
       int zool = braket.indexOf("]",0); 
           if (zool > 0) {
              QString   xid = braket.left(zool);  
               esanummer = xid.toInt();
           }
    }
return esanummer;
}




static inline qreal Pointo( qreal unit , const QString unita )  {
    qreal ri = 0;
    if (unita == "cm") {
    ri = POINT_TO_CM( unit );
    } else if (unita == "pt") {
    ri = unit;
    } else if (unita == "mm") {
    ri = POINT_TO_MM( unit );
    } else if (unita == "dm") {
    ri = POINT_TO_DM( unit );
    } else if (unita == "inch") {
    ri = POINT_TO_INCH( unit );
    } else if (unita == "pi") {
    ri = POINT_TO_PI( unit );
    } else if (unita == "dd") {
    ri = POINT_TO_DD( unit );
    }  else if (unita == "cc") {
    ri = POINT_TO_CC( unit );
    } else {
    ri = 10000;
    }
    
    return ri;
}











static inline qreal FopInt( const QString datain )
{
  QString ctmp = datain;
  const QString data = ctmp.replace(" ","").trimmed();
  //////////qDebug() << "### request unit data->" << datain << " size->" << datain.size();   
  
  qreal points = 0;
  if (data.size() < 1) {
  return points;
  }
  if (datain == "0") {
  return points;
  }
  
  
 
  if ( data.endsWith( "pt" ) ) {
    points = data.left( data.length() - 2 ).toDouble();
  } else if ( data.endsWith( "cm" ) ) {
    double value = data.left( data.length() - 2 ).toDouble();
    points = CM_TO_POINT( value );
  } else if ( data.endsWith( "em" ) ) {
    points = data.left( data.length() - 2 ).toDouble();
  } else if ( data.endsWith( "mm" ) ) {
    double value = data.left( data.length() - 2 ).toDouble();
    points = MM_TO_POINT( value );
  } else if ( data.endsWith( "dm" ) ) {
    double value = data.left( data.length() - 2 ).toDouble();
    points = DM_TO_POINT( value );
  } else if ( data.endsWith( "in" ) ) {
    double value = data.left( data.length() - 2 ).toDouble();
    points = INCH_TO_POINT( value );
  } else if ( data.endsWith( "inch" ) ) {
    double value = data.left( data.length() - 4 ).toDouble();
    points = INCH_TO_POINT( value );
  } else if ( data.endsWith( "pi" ) ) {
    double value = data.left( data.length() - 4 ).toDouble();
    points = PI_TO_POINT( value );
  } else if ( data.endsWith( "dd" ) ) {
    double value = data.left( data.length() - 4 ).toDouble();
    points = DD_TO_POINT( value );
  } else if ( data.endsWith( "cc" ) ) {
    double value = data.left( data.length() - 4 ).toDouble();
    points = CC_TO_POINT( value );
  } else {
    points = 0;
  }
  return points;
}

static inline qreal ToPoint( qreal unit , const QString unita )  {
    qreal ri = 0;
    if (unita == "cm") {
    ri = CM_TO_POINT( unit );
    } else if (unita == "pt") {
    ri = unit;
    } else if (unita == "mm") {
    ri = MM_TO_POINT( unit );
    } else if (unita == "dm") {
    ri = DM_TO_POINT( unit );
    } else if (unita == "inch") {
    ri = INCH_TO_POINT( unit );
    } else if (unita == "pi") {
    ri = PI_TO_POINT( unit );
    } else if (unita == "dd") {
    ri = DD_TO_POINT( unit );
    }  else if (unita == "cc") {
    ri = CC_TO_POINT( unit );
    } else {
    ri = 10000;
    }
    
    return ri;
}

static inline bool AppendImageSVG( QByteArray imagestream , QDomElement e , QDomDocument doc  ) 
{
    bool buildaction = false;
    
    QString errorStr;
    int errorLine, errorColumn, position;
    QDomDocument img;
    if (!img.setContent(imagestream,false, &errorStr, &errorLine, &errorColumn)) {
    return false;
    } 
    QDomElement root_extern = img.documentElement(); 
    root_extern.setTagName("svg:svg");
    QDomNamedNodeMap attlist = root_extern.attributes();   /* copy all attributes from other doc */
    QDomNode newnode = root_extern.firstChild();
    QDomNode treallsub = doc.importNode(newnode,true);
    QDomElement svg = doc.createElement("svg:svg");
      for (int i=0; i<attlist.count(); i++){
        QDomNode nod = attlist.item(i);
        svg.setAttribute(nod.nodeName().toLower(),nod.nodeValue());
      }
    svg.setAttribute ("xmlns","http://www.w3.org/2000/svg");
    svg.setAttribute ("version","1.2");
    svg.setAttribute ("baseProfile","tiny");
      
       QDomNode child = root_extern.firstChild();
       while ( !child.isNull() ) {
           if ( child.isElement() ) {
            svg.appendChild(doc.importNode(child,true).toElement());
           }
         child = child.nextSibling();            
       }
    
   e.appendChild(svg);
   return true;
}


static inline QPixmap RenderPixmapFromSvgByte(  QByteArray streams ) 
{
        QSvgRenderer  svgRenderer( streams );
        QPixmap pix(  svgRenderer.defaultSize() );
        pix.fill(Qt::transparent);
        QPainter paint(&pix);
        svgRenderer.render(&paint);
        return pix;
}






/* simple prepare QTableView - > model to print return QTextDocument */
static inline QTextDocument *TabletoDom( const QStandardItemModel * model , int remove_last_line = 0 )
{
    /* remove last line if needet to remove Empty line to scroll more down on QTableView */
    const int righe = qBound(0,model->rowCount() - remove_last_line ,model->rowCount()); 
    const int colonne = model->columnCount();
    /* normal paragraph format */
    QTextBlockFormat paraformat;
    paraformat.setBottomMargin(0);
    paraformat.setTopMargin(0); 
    /* Empty paragraph format */
    QTextBlockFormat paraspace;
    paraspace.setBottomMargin(8);
    paraspace.setTopMargin(8); 
    QColor BackgroundColor;
    int CursorPointer = 0;
    QTextDocument *doc = new QTextDocument();
    QTextCursor Tcursor = QTextCursor(doc);
    ///////////bool IsCorrectCursor = Tcursor.movePosition(QTextCursor::End);
    CursorPointer = Tcursor.position();
    
    QTextTable *qtable = Tcursor.insertTable(righe+1,colonne);  /////// righe
    QTextTableFormat tableFormat;
    tableFormat.setWidth(QTextLength(QTextLength::PercentageLength,98));
    tableFormat.setBackground ( QColor(Qt::white) );
    tableFormat.setBorder(0);
    tableFormat.setCellSpacing(2);
    tableFormat.setCellPadding(2);
    tableFormat.setAlignment ( Qt::AlignLeft );
    /* START HEADER ONLY ONE TD LINE  */
    for (int e = 0; e < colonne; ++e) {
         const QString testosopra = model->headerData(e,Qt::Horizontal,Qt::DisplayRole).toString();
         QTextTableCell cellheader = qtable->cellAt(0,e);
         /* set cursor position on first cell! */
         Tcursor = cellheader.firstCursorPosition();
                       QFont fx1 = model->headerData(e,Qt::Horizontal,Qt::FontRole).value<QFont>();
                       QColor TextColor1 = model->headerData(e,Qt::Horizontal,Qt::TextColorRole).value<QColor>();
                       ////////QColor BackgroundColor1 = model->headerData(e,Qt::Horizontal,Qt::BackgroundRole).value<QColor>();
                       QTextCharFormat td_format = cellheader.format();
                       td_format.setBackground(QColor("#dfdfdf"));   /* set BG color on header only palette */
                       cellheader.setFormat(td_format);
        
                       QTextCharFormat InlineStyle1;
                       InlineStyle1.setForeground(QBrush(TextColor1));
                       InlineStyle1.setFont(fx1);
                       Tcursor.insertText(testosopra,InlineStyle1);
    /////////////////qDebug() << "testa  ->" << testosopra;
    }
    /* START LINE ROW LOOPS */
        for (int i = 0; i < righe; ++i) {
        
                      for (int o = 0; o < colonne; ++o) {
                       QTextTableCell cellstart = qtable->cellAt(i+1,o);
                       QModelIndex index = model->index(i,o);
                          
                                if (index.isValid ()) {
                                           const QString txt = model->data(index,Qt::DisplayRole).toString();
                                           //////////qDebug() << "corpo  ->" << txt;
                                           QFont fx = model->data(index,Qt::FontRole).value<QFont>();
                                           QColor TextColor = model->data(index,Qt::TextColorRole).value<QColor>();
                                           BackgroundColor = model->data(index,Qt::BackgroundRole).value<QColor>();
                                           /* alignment txt */
                                           paraformat.setAlignment((Qt::Alignment)model->data(index,Qt::TextAlignmentRole).toInt());                                   

                                           if ( !BackgroundColor.isValid ()) {
                                               if (i%2) {
                                                 BackgroundColor = QColor("#e1e1e1");
                                               } else {
                                                 BackgroundColor = QColor("#ffffff");
                                               }
                                           }                                               
                                              
                                           QTextCharFormat existformat = cellstart.format();
                                           existformat.setBackground(BackgroundColor);
                                           cellstart.setFormat(existformat);
                                              
                                           QTextCharFormat InlineStyle;
                                           InlineStyle.setForeground(QBrush(TextColor));
                                           InlineStyle.setFont(fx);
                                              
                                           Tcursor = cellstart.firstCursorPosition();
                                           if (txt.trimmed().size() < 1) {
                                           Tcursor.setBlockFormat(paraspace);
                                           } else {
                                           Tcursor.setBlockFormat(paraformat);
                                           }
                                           
                                           Tcursor.insertText(txt,InlineStyle);
                                }
                      }
        
    }
    
    
    qtable->setFormat( tableFormat );
    /////////QString xdhtml = doc->toHtml("utf-8");
    //////qDebug() << "xdhtml0000000000  ->" << xdhtml;
    return doc;  
}



static inline QDomElement GetDomRoot( QString filexml  )
{
     QDomDocument doc;
     QDomElement root;
     QFile xmlfile( filexml );
     if(!xmlfile.open( QIODevice::ReadOnly ) ) {
      return root;
     }
     if (!doc.setContent(&xmlfile)) {
      xmlfile.close();
      return root;
     }
     root = doc.documentElement();
     return root;
 }
 


 



static inline QString StringtoXML( QString t )
{
  //the following checks are necessary before exporting
  //strings to XML. see http://hdf.ncsa.uiuc.edu/HDF5/XML/xml_escape_chars.html for details
  QString text = t;
  text.replace("&", "&amp;");   /*  qt4 toUtf8 dont replace && */
  text.replace("\"","&quot;");
  text.replace("'", "&apos;");
  text.replace("<", "&lt;");
  text.replace(">", "&gt;");
  text.replace("\n", "&#10;");
  text.replace("\r", "&#13;");
  return text;
}










static inline QStringList GrepNeedField( const  QString html ) 
{
    QStringList UniqueFeName;
    QRegExp expression( "\\b_([A-Z_]+)[_]\\b", Qt::CaseSensitive );
    expression.setMinimal(true);
    int iPosition = 0;
    int canna = -1;
    while( (iPosition = expression.indexIn( html , iPosition )) != -1 ) {
        QString trovo = expression.cap( 1 );
        trovo = trovo.replace("\n","");
        trovo = trovo.replace(" ","");
        if (trovo.size() > 1) {
        canna++;
             if (!UniqueFeName.contains(trovo)) {
               UniqueFeName.append(trovo);
             }
        }
        iPosition += expression.matchedLength();
    }
    return UniqueFeName;
}







static inline QString UriConvert( QString touri )
{
    touri = touri.toLower();
    touri = touri.replace(" ","_");
    QStringList piece = touri.split("");
    QString alloweduri = "abcdefghijklmnopqrstuvwxyz1234567890_";
    QStringList alist = alloweduri.split("");
    
     for (int i = 0; i < piece.size(); ++i) {
           QString pin = piece.at(i);
           if (!alist.contains(pin)) {
               touri.replace(pin,"");
           }
       }
    
    return touri;
}




/* check if a int or float nummer */
static inline bool is_numeric(QString incomming)
{
    incomming.replace(QString(" "), QString("")); /* trimm */
    QString str2 = incomming;
    bool ok; 
    str2.toFloat(&ok); 
return ok;
}










static inline qreal UnitInt( const QString datain )
{
   QString ctmp = datain;
  QString data = ctmp.replace(" ","").trimmed();
    
    
    
  //////////qDebug() << "### request unit data->" << datain << " size->" << datain.size();    
  #define MM_TO_POINT(mm) ((mm)*2.83465058)
  #define CM_TO_POINT(cm) ((cm)*28.3465058)
  #define DM_TO_POINT(dm) ((dm)*283.465058)
  #define INCH_TO_POINT(inch) ((inch)*72.0)
  #define PI_TO_POINT(pi) ((pi)*12)
  #define DD_TO_POINT(dd) ((dd)*154.08124)
  #define CC_TO_POINT(cc) ((cc)*12.840103)
  qreal points = 0;
  if (data.size() < 1) {
  return points;
  }
  
  if ( data.endsWith( "pt" ) ) {
    points = data.left( data.length() - 2 ).toDouble();
  } else if ( data.endsWith( "cm" ) ) {
    double value = data.left( data.length() - 2 ).toDouble();
    points = CM_TO_POINT( value );
  } else if ( data.endsWith( "em" ) ) {
    points = data.left( data.length() - 2 ).toDouble();
  } else if ( data.endsWith( "mm" ) ) {
    double value = data.left( data.length() - 2 ).toDouble();
    points = MM_TO_POINT( value );
  } else if ( data.endsWith( "dm" ) ) {
    double value = data.left( data.length() - 2 ).toDouble();
    points = DM_TO_POINT( value );
  } else if ( data.endsWith( "in" ) ) {
    double value = data.left( data.length() - 2 ).toDouble();
    points = INCH_TO_POINT( value );
  } else if ( data.endsWith( "inch" ) ) {
    double value = data.left( data.length() - 4 ).toDouble();
    points = INCH_TO_POINT( value );
  } else if ( data.endsWith( "pi" ) ) {
    double value = data.left( data.length() - 4 ).toDouble();
    points = PI_TO_POINT( value );
  } else if ( data.endsWith( "dd" ) ) {
    double value = data.left( data.length() - 4 ).toDouble();
    points = DD_TO_POINT( value );
  } else if ( data.endsWith( "cc" ) ) {
    double value = data.left( data.length() - 4 ).toDouble();
    points = CC_TO_POINT( value );
  } else {
    points = 0;
    ////////qDebug( "unknown unit %s", qPrintable( datain ) );
    QMessageBox::warning(0,"Unit converter",QString("unknown Unit \"%1\"").arg(datain));
  }

  return points;
}


static inline void OpenDeskBrowser( QUrl loc )
{
    #if defined Q_WS_MAC
    QProcess *m = new QProcess();
    QStringList macs;
    macs << loc.toString();  /* oeffnet der default browser */
    m->startDetached(QString("open") , macs );
    ///////std::cout << "OpenDesktop [" << qPrintable(macs.join(" ")) << "]" << std::endl;
    return;
    #endif 
    
#if defined Q_WS_WIN
    
    QString fullFileName = loc.toString();
    
    if (fullFileName.startsWith("http://", Qt::CaseInsensitive) ||
        fullFileName.startsWith("https://", Qt::CaseInsensitive) ||
        fullFileName.startsWith("ftp://", Qt::CaseInsensitive) ||
        fullFileName.startsWith("news://", Qt::CaseInsensitive) ||
        fullFileName.startsWith("mailto:", Qt::CaseInsensitive) ||
        fullFileName.startsWith("webdav://", Qt::CaseInsensitive)  )
       { 
         /* all ok */
       } else {
         fullFileName.prepend("file:///");  
       }
    bool wr = QDesktopServices::openUrl(QUrl(fullFileName));
    if (!wr) {
    QMessageBox::warning(0, qApp->tr("Error"),qApp->tr("Window Unable to open action file or dir  %1").arg(loc.toString()));
    }
return;
#endif
    
    /* linux */

     bool r = QDesktopServices::openUrl(loc);
    if (!r) {
    QMessageBox::warning(0, qApp->tr("Error"),qApp->tr("Linux Unable to open action file or dir  %1").arg(loc.toString()));
    }
    
}





#include "DB_Manager.h"



#endif /*CONFIG_H_*/
